package com.example.usercenter.server;

import com.example.usercenter.common.Result;
import com.example.usercenter.exception.ServiceException;
import com.example.usercenter.model.request.SocketMessage;
import com.example.usercenter.model.vo.WebSocketResult;
import com.google.gson.Gson;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket服务端
 * @author 米饭好好吃
 */
@ServerEndpoint("/chat/{userAccount}")
@Component
@Slf4j
public class WebSocketServer {

    /**
     * 保存用户连接信息
     */
    private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("userAccount") String userAccount) {
        // 1. 加入连接信息
        sessionMap.put(userAccount, session);
        log.info("用户" + userAccount + "已上线，目前在线人数：" + sessionMap.size());
        // 2. 告诉客户端全部在线用户 TODO: 前端能够获取到所有在线用户数据
        sendAllOnLineUsers();
    }

    /**
     * 返回所有在线用户信息
     */
    private void sendAllOnLineUsers() {
        Gson gson = new Gson();
        // 1. 封裝在线用户列表
        Map<String, String> userListMap = new HashMap<>();
        for (String userAccount : sessionMap.keySet()) {
            userListMap.put(userAccount, userAccount);
        }
        // 2. 将在线用户列表反序列化
        WebSocketResult<Map<String, String>> result = new WebSocketResult<>("onLineUserList", userListMap);
        log.info("在线用户列表:" + result);
        String onLineUserListStr = gson.toJson(result);
        for (Session session : sessionMap.values()) {
            try {
                session.getBasicRemote().sendText(onLineUserListStr);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("userAccount") String userAccount) {
        // 1. 将String类型解析为JSON格式
        Gson gson = new Gson();
        SocketMessage messageObj = gson.fromJson(message, SocketMessage.class);
        // 2. 取出发送者、接受者、消息文本
        String sender = messageObj.getFrom();
        String receiver = messageObj.getTo();
        String text = messageObj.getText();
        // 3. 判断接受者是否在线
        log.info(sender + "给" + receiver + "发送消息：" + text);
        Session receiverSession = sessionMap.get(receiver);
        if (receiverSession == null) {
            log.info("接受者" + receiver + "不在线，发送失败！");
            return;
        }
        // 3. 通知接受者
        sendMessage(messageObj, receiverSession);
    }

    public void sendMessage(SocketMessage messageObj, Session receiverSession) {
        try {
            // 1. 封装数据消息
            WebSocketResult<SocketMessage> result = new WebSocketResult<>("msg", messageObj);
            // 2. 转换成json格式
            Gson gson = new Gson();
            String text = gson.toJson(result);
            receiverSession.getBasicRemote().sendText(text);
        } catch (IOException e) {
            throw new ServiceException(500, e.getMessage());
        }
    }

    @OnClose
    public void onClose(@PathParam("userAccount") String userAccount) {
        log.info("用户：" + userAccount + "下线！");
        if (!sessionMap.containsKey(userAccount)) {
            return;
        }
        sessionMap.remove(userAccount);
    }

    @OnError
    public void onError(Session session, Throwable th) {
        th.printStackTrace();
    }


}
